#include "pageuart.h"
#include <QDebug>
#include "str.h"
#include "application.h"
#include "modulemanager.h"
#include "portmanager.h"

PageUart::PageUart(QWidget *parent)
    : QWidget (parent)
{
    qDebug() << "PageUart...";

    // widget
    setWindowTitle(tr("Uart"));
    setAttribute(Qt::WA_DeleteOnClose, true);

    // controls
    lbPort = new QLabel();
    lbPort->setText(tr("Port"));
    cbPort = new QComboBox();
    findPortManagerPorts();
    connect(cbPort, SIGNAL(currentIndexChanged(int)), this, SLOT(onPortChanged(int)));
    QHBoxLayout *hblPort = new QHBoxLayout();
    hblPort->addWidget(lbPort);
    hblPort->addWidget(cbPort);

    // receive config
    rbReceiveASCII = new QRadioButton();
    rbReceiveASCII->setText(tr("ASCII"));
    rbReceiveHEX = new QRadioButton();
    rbReceiveHEX->setText(tr("HEX"));
    QButtonGroup *bgReceiveAscii = new QButtonGroup(this);
    bgReceiveAscii->addButton(rbReceiveASCII);
    bgReceiveAscii->addButton(rbReceiveHEX);
    rbReceiveASCII->setChecked(true);
    ckbNewLine = new QCheckBox();
    ckbNewLine->setText(tr("AutoNewLine"));
    ckbShow = new QCheckBox();
    ckbShow->setText(tr("Show"));
    pbReceiveClear = new QPushButton();
    pbReceiveClear->setText(tr("Clear"));

    QHBoxLayout *hblReceiveAscii = new QHBoxLayout();
    hblReceiveAscii->addWidget(rbReceiveASCII, 1);
    hblReceiveAscii->addWidget(rbReceiveHEX, 1);
    QVBoxLayout *vblReceiveConfig= new QVBoxLayout();
    vblReceiveConfig->addLayout(hblReceiveAscii);
    vblReceiveConfig->addWidget(ckbNewLine, 1);
    vblReceiveConfig->addWidget(ckbShow, 1);
    vblReceiveConfig->addWidget(pbReceiveClear, 1);

    QGroupBox *gbReceiveConfig = new QGroupBox();
    gbReceiveConfig->setTitle(tr("Receive Config"));
    gbReceiveConfig->setLayout(vblReceiveConfig);

    // send config
    rbSendASCII = new QRadioButton();
    rbSendASCII->setText(tr("ASCII"));
    rbSendHEX = new QRadioButton();
    rbSendHEX->setText(tr("HEX"));
    QButtonGroup *bgSendAscii = new QButtonGroup(this);
    bgSendAscii->addButton(rbSendASCII);
    bgSendAscii->addButton(rbSendHEX);
    rbSendASCII->setChecked(true);
    ckbTransfer = new QCheckBox();
    ckbTransfer->setText(tr("AutoTransfer"));
    ckbPeriod = new QCheckBox();
    ckbPeriod->setText(tr("Period"));
    lePeriod = new QLineEdit();
    QLabel *lbPeriodUnit = new QLabel();
    lbPeriodUnit->setText(tr("ms"));
    pbSendClear = new QPushButton();
    pbSendClear->setText(tr("Clear"));

    QHBoxLayout *hblSendAscii = new QHBoxLayout();
    hblSendAscii->addWidget(rbSendASCII, 1);
    hblSendAscii->addWidget(rbSendHEX, 1);
    QHBoxLayout *hblSendPeroid = new QHBoxLayout();
    hblSendPeroid->addWidget(lePeriod, 1);
    hblSendPeroid->addWidget(lbPeriodUnit, 1);
    QVBoxLayout *vblSendConfig= new QVBoxLayout();
    vblSendConfig->addLayout(hblSendAscii);
    vblSendConfig->addWidget(ckbTransfer, 1);
    vblSendConfig->addWidget(ckbPeriod, 1);
    vblSendConfig->addLayout(hblSendPeroid, 1);
    vblSendConfig->addWidget(pbSendClear, 1);

    QGroupBox *gbSendConfig = new QGroupBox();
    gbSendConfig->setTitle(tr("Send Config"));
    gbSendConfig->setLayout(vblSendConfig);

    // receive area
    QWidget *widDataReceive = new QWidget();
    teDataReceive = new QTextEdit();
    QVBoxLayout *vblDataReceive = new QVBoxLayout();
    vblDataReceive->addWidget(teDataReceive);
    widDataReceive->setLayout(vblDataReceive);

    QTabWidget *tabWidgetReceive = new QTabWidget();
    tabWidgetReceive->addTab(widDataReceive, tr("Receive Data"));

    QWidget *widDataSend = new QWidget();
    leDataSend = new QLineEdit();
    pbSend = new QPushButton();
    pbSend->setText(tr("Send"));
    QHBoxLayout *hblDataSend = new QHBoxLayout();
    hblDataSend->addWidget(leDataSend, 8);
    hblDataSend->addWidget(pbSend, 1);
    widDataSend->setLayout(hblDataSend);

    QTabWidget *tabWidgetSend = new QTabWidget();
    tabWidgetSend->addTab(widDataSend, tr("Send Data"));

    lbRXTXTimes = new QLabel();
    lbRXTXTimes->setText("0/0");
    lbRXCnt = new QLabel();
    lbRXCnt->setText(tr("RX:0"));
    lbTXCnt = new QLabel();
    lbTXCnt->setText(tr("TX:0"));
    pbCntClear = new QPushButton();
    pbCntClear->setText(tr("Clear"));
    QHBoxLayout *hblStatistic = new QHBoxLayout();
    hblStatistic->addWidget(lbRXTXTimes, 1);
    hblStatistic->addWidget(lbRXCnt, 1);
    hblStatistic->addWidget(lbTXCnt, 1);
    hblStatistic->addWidget(pbCntClear, 1);

    // layout
    QVBoxLayout *vblConfig = new QVBoxLayout();
    vblConfig->addLayout(hblPort, 1);
    vblConfig->addWidget(gbReceiveConfig, 1);
    vblConfig->addWidget(gbSendConfig, 1);
    QVBoxLayout *vblData = new QVBoxLayout();
    vblData->addWidget(tabWidgetReceive, 8);
    vblData->addWidget(tabWidgetSend, 1);
    vblData->addLayout(hblStatistic, 1);

    QHBoxLayout *hbl = new QHBoxLayout();
    hbl->addLayout(vblConfig, 2);
    hbl->addLayout(vblData, 3);
    setLayout(hbl);

    // statistic
    timerPeriod = new QTimer(this);
    connect(timerPeriod, &QTimer::timeout, this, &PageUart::onTimeout);
    rxCnt = 0;
    txCnt = 0;
    lbRXCnt->setText(tr("RX:%1").arg(rxCnt));
    lbTXCnt->setText(tr("TX:%1").arg(txCnt));

    rxTimes = 0;
    txTimes = 0;
    lbRXTXTimes->setText(QString("%1/%2").arg(rxTimes).arg(txTimes));

    // connect
    connect(pbReceiveClear, &QPushButton::clicked, [=](){
        teDataReceive->clear();
    });
    connect(pbSendClear, &QPushButton::clicked, [=](){
        leDataSend->clear();
    });
    connect(pbCntClear, &QPushButton::clicked, [=](){
        rxCnt = 0;
        txCnt = 0;
        lbRXCnt->setText(tr("RX:%1").arg(rxCnt));
        lbTXCnt->setText(tr("TX:%1").arg(txCnt));

        rxTimes = 0;
        txTimes = 0;
        lbRXTXTimes->setText(QString("%1/%2").arg(rxTimes).arg(txTimes));
    });
    connect(pbSend, &QPushButton::clicked, [=](){
        if(ckbPeriod->isChecked())
        {
            qint32 period = lePeriod->text().toInt();
            if(period > 0)
            {
                if(pbSend->text() == tr("send"))
                {
                    send(); //先发送一次
                    timerPeriod->setInterval(period);
                    timerPeriod->start();
                    pbSend->setText(tr("stop"));
                    ckbPeriod->setEnabled(false);
                    lePeriod->setEnabled(false);
                }
                else
                {
                    timerPeriod->stop();
                    pbSend->setText(tr("send"));
                    ckbPeriod->setEnabled(true);
                    lePeriod->setEnabled(true);
                }
            }
        }
        else
            send();
    });

    qDebug() << "PageUart...completed";
}

void PageUart::onReceiveData(const QByteArray data)
{
    if(ckbShow->isChecked())
    {
        if(rbReceiveASCII->isChecked())
        {
            teDataReceive->moveCursor(QTextCursor::End);
            if(ckbNewLine->isChecked())
                teDataReceive->append(data);
            else
                teDataReceive->insertPlainText(data);
        }
        else
        {
            QString str;
            str::hex2String(data, &str);
            if(ckbNewLine->isChecked())
                teDataReceive->append(str);
            else
                teDataReceive->insertPlainText(str);
        }
    }
    rxCnt += data.length();
    lbRXCnt->setText(tr("RX:%1").arg(rxCnt));

    rxTimes++;
    lbRXTXTimes->setText(QString("%1/%2").arg(rxTimes).arg(txTimes));
}

void PageUart::onTimeout(void)
{
    send();
}

void PageUart::onPortChanged(int index)
{
    setSerialPort(*m_ports.at(index));
}

void PageUart::send(void)
{
    QString strSend = leDataSend->text();
    if(!strSend.isEmpty())
    {
        if(rbSendASCII->isChecked())
        {
            if(ckbTransfer->isChecked())
            {
                QString str = str::stringTransfer(strSend);
                emit write(str.toUtf8());
                txCnt += str.length();
            }
            else
            {
                emit write(strSend.toUtf8());
                txCnt += strSend.length();
            }
        }
        else
        {
            QByteArray ba;
            strSend.remove(QRegExp("\\s")); //去掉所有空格
            str::string2Hex(strSend, &ba);
            emit write(ba);
            txCnt += strSend.length();
        }
        lbTXCnt->setText(tr("TX:%1").arg(txCnt));

        txTimes++;
        lbRXTXTimes->setText(tr("%1/%2").arg(rxTimes).arg(txTimes));
    }
}

void PageUart::findPortManagerPorts()
{
    cbPort->clear();
    m_ports.clear();

    QList<BasePort*> ports = portManager->getAllPorts();
    foreach (BasePort *p, ports) {
        if (p->getPortType() == BasePort::PortType_Serial)
        {
            cbPort->addItem(p->getName());
            m_ports << static_cast<SerialPort*>(p);
        }
    }

    m_port = m_ports.at(0);
}

void PageUart::setSerialPort(SerialPort &port)
{
    disconnect(m_port, &BasePort::readCompleted, this, &PageUart::onReceiveData);
    disconnect(this, &PageUart::write, m_port, &BasePort::onSend);

    disconnect(cbPort, SIGNAL(currentIndexChanged(int)), this, SLOT(onPortChanged(int)));
    cbPort->setCurrentText(port.getName());
    connect(cbPort, SIGNAL(currentIndexChanged(int)), this, SLOT(onPortChanged(int)));

    m_port = &port;
    connect(m_port, &BasePort::readCompleted, this, &PageUart::onReceiveData, Qt::QueuedConnection);
    connect(this, &PageUart::write, m_port, &BasePort::onSend, Qt::QueuedConnection);
}
